#include <SPI.h>
#include <protocentral_Max30003.h>
#include <Wire.h>
#include <driver/timer.h>
#include <SparkFun_LIS2DH12.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#include <Arduino.h>

#include <sstream>
#include <string>

#include <SparkFun_ST25DV64KC_Arduino_Library.h> // Click here to get the library:  http://librarymanager/All#SparkFun_ST25DV64KC

#include <ESP32Time.h>

#include "algorithm/algorithm.h"
#include "algorithm/filter.h"
#include "algorithm/algo_ecg_calculate_hr.h"
#include "fdc2214/FDC2214.h"
FDC2214 capsense(FDC2214_I2C_ADDR_0); // Use FDC2214_I2C_ADDR_1 

ESP32Time rtc(-8*3600);  // offset in seconds GMT+0

uint16_t SMARTAG_END_ADDR_COMPACT_DATA   = 8192;
uint16_t SMARTAG_BEGIN_ADDR_COMPACT_DATA = 120;
uint16_t LastSamplePointer = SMARTAG_BEGIN_ADDR_COMPACT_DATA;
uint8_t  nfc_write_notify = 0;

SFE_ST25DV64KC_NDEF tag;

#pragma pack(1)
typedef enum {
    BLE_SEND_ECG_DATA,
	BLE_SEND_ACC_DATA,
	BLE_SEND_HR_DATA,
	MSG_REC_ACC_DATA,
} sys_event_type_t;

typedef struct {
	sys_event_type_t type;
    float* Fdata;
	unsigned int heartRate;//心率
	unsigned int RRinterval;//心率间隔
	uint8_t* ecgdata;
	uint16_t size;
} sys_event_t;

typedef struct
{
    float     acc_x;
    float     acc_y;
    float     acc_z;
}ACC_DATA_T;
#pragma pack()

static SemaphoreHandle_t MuxSem_Handle = xSemaphoreCreateMutex();
static QueueHandle_t sys_queue;
static sys_event_t usr_ecg_event;
static sys_event_t usr_acc_event;
static void acc_message_send(sys_event_t event);
void usr_ble_ecg_data_send(uint8_t* ecgdata, uint16_t size);
void usr_ble_acc_data_send(float* fdata);

MAX30003 max30003;
SPARKFUN_LIS2DH12 accel; // Create instance

uint8_t txValue = 0;
BLEServer *pServer = NULL;					 // BLEServer指针 pServer
BLECharacteristic *pTxCharacteristic = NULL; // BLECharacteristic指针 pTxCharacteristic
BLECharacteristic *pTxCharacteristic_2 = NULL; // BLECharacteristic指针 pTxCharacteristic_2
bool deviceConnected = false;				 // 本次连接状态
bool oldDeviceConnected = false;			 // 上次连接状态

// See the following for generating UUIDs: https://www.uuidgenerator.net/
#define SERVICE_UUID "8b3bd5f2-d9f6-4627-8d4a-95528b20f5ed" // UART service UUID
#define CHARACTERISTIC_UUID_RX "33bd79a8-fc9a-4201-b682-2b029130b90e"
#define CHARACTERISTIC_UUID_TX "c48d0417-de7a-41ef-b34c-1c1f0202a53f"
#define CHARACTERISTIC_UUID_TX_2 "c48d0418-de7a-41ef-b34c-1c1f0202a53f"

#define USE_MULTCORE 0

/* NFC field */
#define FIELD_FALLING 0   //RF场下降
#define FIELD_RISING  1   //RF场上升
#define FIELD_UNDEF   2   
static uint32_t RFActivityStatus = FIELD_UNDEF;
static volatile uint32_t RFActivity = 1;

/* Dynamic Registers i2c address */
/** @brief ST25DV GPO dynamic register address. */
#define ST25DV_GPO_DYN_REG                   0x2000
/** @brief ST25DV Energy Harvesting control dynamic register address. */
#define ST25DV_EH_CTRL_DYN_REG               0x2002
/** @brief ST25DV RF management dynamic register address. */
#define ST25DV_RF_MNGT_DYN_REG               0x2003
/** @brief ST25DV I2C secure session opened dynamic register address. */
#define ST25DV_I2C_SSO_DYN_REG               0x2004
/** @brief ST25DV Interrupt status dynamic register address. */
#define ST25DV_ITSTS_DYN_REG                 0x2005
/** @brief ST25DV Mailbox control dynamic register address. */
#define ST25DV_MB_CTRL_DYN_REG               0x2006
/** @brief ST25DV Mailbox message length dynamic register address. */
#define ST25DV_MBLEN_DYN_REG                 0x2007
/** @brief ST25DV Mailbox buffer address. */
#define ST25DV_MAILBOX_RAM_REG               0x2008

static struct tm timeinfo;
/**
 * @brief 获取RTC时间
 * tm_year : bit31-bit26
 * tm_mday : bit25-bit21
 * tm_mon  : bit20-bit17 
 * tm_hour : bit16-bit12
 * tm_min  : bit11-bit6
 * tm_sec  : bit5-bit0
 * @return uint32_t 
 */
uint32_t RTC_GetDateTime(void)
{
	uint32_t DateTime = 0;
	timeinfo = rtc.getTimeStruct();
	/* 6 bits, years since DATETIME_BASEYEAR */
 	DateTime  = (((uint32_t) ((timeinfo.tm_year - 70) &0x3F)) << 26);
  	/* 5 bits */
  	DateTime |= (((uint32_t) (timeinfo.tm_mday     )) << 21);
  	/* 4 bits */
  	DateTime |= (((uint32_t) (timeinfo.tm_mon + 1  )) << 17);
  	/* 5 bits */
  	DateTime |= (((uint32_t) (timeinfo.tm_hour     )) << 12);
  	/* 6 bits */
  	DateTime |= (((uint32_t) (timeinfo.tm_min      )) <<  6);
  	/* 6 bits */
  	DateTime |= (((uint32_t) (timeinfo.tm_sec      ))      );
	//Serial.println(DateTime, HEX);
	//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
	return DateTime;
}

/**
 * @brief 用于检测ST25DV16 GPO引脚中断
 * 
 */
struct Button {
    const uint8_t PIN;
    uint32_t numberKeyPresses;
    bool pressed;
};

Button button1 = {15, 0, false};

void ARDUINO_ISR_ATTR isr(void* arg) {
    Button* s = static_cast<Button*>(arg);
    s->numberKeyPresses += 1;
    s->pressed = true;
}

class MyServerCallbacks : public BLEServerCallbacks
{
	void onConnect(BLEServer *pServer)
	{
		deviceConnected = true;
	};

	void onDisconnect(BLEServer *pServer)
	{
		deviceConnected = false;
	}
};

class MyCallbacks : public BLECharacteristicCallbacks
{
	void onWrite(BLECharacteristic *pCharacteristic)
	{
		std::string rxValue = pCharacteristic->getValue(); // 接收信息

		if (rxValue.length() > 0)
		{ // 向串口输出收到的值
			Serial.print("RX: ");
			for (int i = 0; i < rxValue.length(); i++)
				Serial.print(rxValue[i]);
			Serial.println();
		}

		/* 手机通过BLE向ESP32校准时间 */
		if(rxValue.length() >= 19)
		{
			int year   = (rxValue[0]-0x30)*1000 + (rxValue[1]-0x30)*100 + (rxValue[2]-0x30)*10 + (rxValue[3]-0x30);
			int month  = (rxValue[5]-0x30)*10+(rxValue[6]-0x30);
			int day    = (rxValue[8]-0x30)*10+(rxValue[9]-0x30);
			int hour   = (rxValue[11]-0x30)*10+(rxValue[12]-0x30);
			int minute = (rxValue[14]-0x30)*10+(rxValue[15]-0x30);
			int second = (rxValue[17]-0x30)*10+(rxValue[18]-0x30);
			rtc.setTime(second, minute, hour, day, month, year);//设置RTC时间
		}
		
	}
};

void BLE_Init(void)
{
	// 创建一个 BLE 设备
	BLEDevice::init("UART_BLE");

	// 创建一个 BLE 服务
	pServer = BLEDevice::createServer();
	pServer->setCallbacks(new MyServerCallbacks()); // 设置回调
	BLEService *pService = pServer->createService(SERVICE_UUID);

	// 创建一个 BLE 特征
	pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);//ecg数据
	pTxCharacteristic->addDescriptor(new BLE2902());
	pTxCharacteristic_2 = pService->createCharacteristic(CHARACTERISTIC_UUID_TX_2, BLECharacteristic::PROPERTY_NOTIFY);//心率、加速度、温度
	pTxCharacteristic_2->addDescriptor(new BLE2902());
	BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
	pRxCharacteristic->setCallbacks(new MyCallbacks()); // 设置回调

	pService->start();					// 开始服务
	pServer->getAdvertising()->start(); // 开始广播
	Serial.println(" 等待一个客户端连接，且发送通知... ");
}

void BLE_Connection_Status(void)
{
	// deviceConnected 已连接
	if (deviceConnected)
	{
		#if 0
		pTxCharacteristic->setValue(&txValue, 1); // 设置要发送的值为1
		pTxCharacteristic->notify();			  // 广播
		txValue++;								  // 指针地址自加1
												  // delay(2000);                           // 如果有太多包要发送，蓝牙会堵塞
		#endif
	}
	// disconnecting  断开连接
	if (!deviceConnected && oldDeviceConnected)
	{
		delay(500);					 // 留时间给蓝牙缓冲
		pServer->startAdvertising(); // 重新广播
		Serial.println(" 开始广播 ");
		oldDeviceConnected = deviceConnected;
	}

	// connecting  正在连接
	if (deviceConnected && !oldDeviceConnected)
	{
		// do stuff here on connecting
		oldDeviceConnected = deviceConnected;
	}
}

void max30003_Init(void)
{
	pinMode(MAX30003_CS_PIN, OUTPUT);
	digitalWrite(MAX30003_CS_PIN, HIGH); // disable device

	// SPI.begin(18, 19, 23, 5); //VSPI
	SPI.begin();
	SPI.setBitOrder(MSBFIRST);
	SPI.setDataMode(SPI_MODE0);
	pinMode(FCLK_PIN, OUTPUT);

	bool ret = max30003.max30003ReadInfo();
	if (ret)
	{
		Serial.println("Max30003 read ID Success");
	}
	else
	{
		while (!ret)
		{
			// stay here untill the issue is fixed.
			ret = max30003.max30003ReadInfo();
			Serial.println("Failed to read ID, please make sure all the pins are connected");
			delay(10000);
		}
	}

	Serial.println("Initialising the chip ...");
	max30003.max30003Begin2(); // initialize MAX30003
}

void accel_LIS2DH12_Init(void)
{
	Serial.println("SparkFun Accel Example");
	Wire.begin();

	if (accel.begin() == false)
	{
		Serial.println("Accelerometer not detected. Check address jumper and wiring. Freezing...");
		while (1);
	}
}

// Max30003
void xTaskOne(void *xTask1)
{
	uint8_t ecg_buf[32*sizeof(signed long)];
	while (1)
	{
#if 0
		//max30003.getHRandRR();
		for(int i=0; i<32; i++)
		{
			max30003.getEcgSamples(); // It reads the ecg sample and stores it to max30003.ecgdata.
			float ecg_mv = 0.000381469 * max30003.ecgdata;
			
			float ecg = max30003.ecgdata;
			ecg_buf[0 + i*4] = ((uint8_t*)&ecg)[0];
			ecg_buf[1 + i*4] = ((uint8_t*)&ecg)[1];
			ecg_buf[2 + i*4] = ((uint8_t*)&ecg)[2];
			ecg_buf[3 + i*4] = ((uint8_t*)&ecg)[3];
		}
		usr_ble_ecg_data_send(ecg_buf, 32*sizeof(signed long));
#endif
		delay(10);
	}
}

// LIS2DH12
static ACC_DATA_T acc_data[FR_ACC] = {0}; 
uint16_t acc_data_len = 0;

void xTaskTwo(void *xTask2)
{
	float sendBuf[4];
	static sys_event_t msg;
	while (1)
	{
		// Print accel values only if new data is available
		if (accel.available())
		{
			float accelX = accel.getX();
			float accelY = accel.getY();
			float accelZ = accel.getZ();
			float tempC  = accel.getTemperature();

			sendBuf[0] = accelX;
			sendBuf[1] = accelY;
			sendBuf[2] = accelZ;
			sendBuf[3] = tempC;

			usr_ble_acc_data_send(sendBuf);

			#if 1
			acc_data[acc_data_len].acc_x = accelX;
			acc_data[acc_data_len].acc_y = accelY;
			acc_data[acc_data_len].acc_z = accelZ;
			acc_data_len++;
			if (acc_data_len >= 22)
			{
 				msg.type  = MSG_REC_ACC_DATA;
            	msg.size  = acc_data_len;
            	msg.Fdata = (float*)&acc_data;
				xSemaphoreTake(MuxSem_Handle, portMAX_DELAY);
				xQueueSend(sys_queue, &msg, 10);
				xSemaphoreGive(MuxSem_Handle);
				acc_data_len = 0;
			}
			#endif
		}
		delay(10);
	}
}

/*****************************************************************************/
static void ecg_message_send(sys_event_t event)
{
    if (NULL != sys_queue)
    {
        xQueueSend(sys_queue, &event, 10);
    }
}

static void acc_message_send(sys_event_t event)
{
    if (NULL != sys_queue)
    {
    	xQueueSend(sys_queue, &event, 10);
    }
}

void usr_ble_ecg_data_send(uint8_t* ecgdata, uint16_t size)
{
	usr_ecg_event.type = BLE_SEND_ECG_DATA;
	usr_ecg_event.ecgdata = ecgdata;
	usr_ecg_event.size = size;
	xSemaphoreTake(MuxSem_Handle, portMAX_DELAY);
	ecg_message_send(usr_ecg_event);
	xSemaphoreGive(MuxSem_Handle);
}

void usr_ble_acc_data_send(float* fdata)
{
	usr_acc_event.type = BLE_SEND_ACC_DATA;
	usr_acc_event.Fdata = fdata;
	xSemaphoreTake(MuxSem_Handle, portMAX_DELAY);
	acc_message_send(usr_acc_event);
	xSemaphoreGive(MuxSem_Handle);
}

static float sendECG[32];
static float ecg_calculate_buf[2*256];
static void xTaskThree(void *xTask3)
{
	sys_queue = xQueueCreate(60, sizeof(sys_event_t));
	static sys_event_t event;
	static uint16_t ecg_calculate_index = 0;
	boolean hr_calculate_flag = false;//计算心率标志位
	while(1)
	{
 		if(xQueueReceive(sys_queue, (void *)&event, (TickType_t)(portMAX_DELAY)))
        {
        	switch(event.type)
        	{
        		case BLE_SEND_ECG_DATA:
        		{
				#if 1
					for(int i = 0; i<(event.size/4); i++) 
					{
						float ecg = 0;
						((uint8_t*)&ecg)[0] = event.ecgdata[0+4*i];
						((uint8_t*)&ecg)[1] = event.ecgdata[1+4*i];
						((uint8_t*)&ecg)[2] = event.ecgdata[2+4*i];
						((uint8_t*)&ecg)[3] = event.ecgdata[3+4*i];
						double ecg1 = ecg;
						ecg1 = filter0(ecg1);
                    	ecg1 = filter1(ecg1);
                    	ecg1 = filter2(ecg1);	
						ecg1 = -ecg1;
						sendECG[i] = ecg1;
						//Serial.printf("ecg = %f\r\n",sendECG[i]);

						ecg_calculate_buf[ecg_calculate_index++] = sendECG[i];
 						if(ecg_calculate_index == 2*256){
                        	ecg_calculate_index = 0;
                        	hr_calculate_flag = true;
                    	}
					}
					pTxCharacteristic->setValue((uint8_t*)&sendECG, event.size);
					pTxCharacteristic->notify();
					if(hr_calculate_flag==true)
					{
						findPeaks(ecg_calculate_buf, 2*256);
						hr_calculate_flag = false;
                    	//Serial.printf("hr = %d\r\n", hr);
						std::stringstream ss;
						std::string buf;
    					ss << "hr:" << hr << ",rri:" << rri_avg;
    					buf = ss.str();
						pTxCharacteristic_2->setValue((uint8_t*)buf.c_str(), buf.length());
						pTxCharacteristic_2->notify();
						//Serial.printf("%s\r\n",buf.c_str());
					}
				#else
        			//pTxCharacteristic->setValue(event.ecgdata, event.size);
					//pTxCharacteristic->notify();
				#endif
        		}break;
				case BLE_SEND_ACC_DATA:
        		{
					//printf("BLE_SEND_ACC_DATA\r\n");
					std::stringstream ss;
					std::string buf;
    				ss << "accx:" << event.Fdata[0] << ",accy:" << event.Fdata[1] << ",accz:" << event.Fdata[2] << ",tempc:"<<event.Fdata[3];
    				buf = ss.str();
					pTxCharacteristic_2->setValue((uint8_t*)buf.c_str(), buf.length());
					pTxCharacteristic_2->notify();

					#if 0
					if (button1.pressed) {
        				Serial.printf("Button 1 has been pressed %u times\n", button1.numberKeyPresses);
        				button1.pressed = false;
						RFActivity = 1;
					}

					/* 检测NFC有没有中断 */
					if(RFActivity)
					{
						RFActivity = 0;
						uint8_t ITStatus = 0;
						tag.readEEPROM(ST25DV_ITSTS_DYN_REG, &ITStatus, 1);
						if(ITStatus&0x10)
						{
							RFActivityStatus = FIELD_RISING;
							Serial.println("Detected NFC FIELD_RISING");
						}else if(ITStatus&0x08)
						{
							RFActivityStatus = FIELD_FALLING;
							Serial.println("Detected NFC FIELD_FALLING");
						}
					}
					
					if(RFActivityStatus == FIELD_FALLING)
					{
						if(nfc_write_notify == 1){
							/* 写入时间戳 */
							//uint32_t DateAndTime = RTC_GetDateTime();
							uint32_t DateAndTime = rtc.getEpoch(); // 返回 Unix 时间戳
  							Serial.printf("timestamp: %d\n", DateAndTime);

							if(!tag.writeEEPROM(LastSamplePointer, (uint8_t *)&DateAndTime, 4))
							{
								Serial.println("write error");
								break;
							}

							tag.writeEEPROM(108, (uint8_t *)&DateAndTime, 4);//写最新时间戳
							tag.writeEEPROM(112, (uint8_t *)&LastSamplePointer, 4);//写最新的地址;
							Serial.printf("%d, %#x\r\n",LastSamplePointer, DateAndTime);
							LastSamplePointer += 4;
			
							/**
						 	* bit[7,0] hr
						 	* bit[23,8] steps
						 	* bit[32,24] temperature
							*/
							uint8_t  hr_t     = hr;
							uint16_t steps  = g_step_total;
							int8_t  temperature = event.Fdata[3];
							uint32_t CompactData = (uint32_t)temperature<<24 | (uint32_t)steps<<8 | (uint32_t)hr_t;

							if(!tag.writeEEPROM(LastSamplePointer, (uint8_t *)&CompactData, 4))
							{
								Serial.println("write error");
								break;
							}
							Serial.printf("%d, %#x\r\n",LastSamplePointer, CompactData);
							LastSamplePointer += 4;

							/* 如果超过最大EEPROM size，则从起点写入 */
							if (LastSamplePointer >= SMARTAG_END_ADDR_COMPACT_DATA) {
								Serial.println("\r\n\r\n!!Reached the End of the TAG\r\n\toverwriting oldest samples!!\r\n\r\n");
    							LastSamplePointer = SMARTAG_BEGIN_ADDR_COMPACT_DATA; 
							}
							nfc_write_notify = 0;
						}
					}
					#endif
        		}break;

				case MSG_REC_ACC_DATA:
				{
					ACC_DATA_T* pAcc_data  = (ACC_DATA_T*)event.Fdata;
					uint16_t  acc_data_cnt = event.size;
					for(int i=0; i<acc_data_cnt; i++)
					{
						data_collect_Acc(pAcc_data[i].acc_x,pAcc_data[i].acc_y,pAcc_data[i].acc_z);
					}
				}break;
        	}
        }
	}
}

// ### Tell aplication how many chanels will be smapled in main loop
#define CHAN_COUNT 2 
void xTaskForth(void *xTask)
{
	static uint32_t reg = 0;
	while (1)
	{
#if 0
		unsigned long capa[CHAN_COUNT]; // variable to store data from FDC
		for (int i = 0; i < CHAN_COUNT; i++){ // for each channel
		  // ### read 28bit data
		  capa[i]= capsense.getReading28(i);//  
		  // ### Transmit data to serial in simple format readable by SerialPlot application.
		  if (i < CHAN_COUNT-1) {
			  Serial.printf("{channel0:%d}\r\n",capa[i]);
		  }
		  else {
			  //Serial.printf("{channel1:%d}\r\n",capa[i]);
		  }
		}
#endif
		delay(10);
	}
}

#define  LED_PIN  27
uint8_t led_state = 0;
void InitLed()
{
	  // 初始化 GPIO27 为输出模式
	  pinMode(LED_PIN, OUTPUT);
	  // 设置 GPIO27 为低电平
	  digitalWrite(LED_PIN, led_state);
}
void toggleLed()
{
	led_state = !led_state;
	digitalWrite(LED_PIN, led_state);
}


//******************************************************* */
// 定义引脚
const int inputPin = 32;  // GPIO32 作为输入

// 中断处理函数（需放在 IRAM_ATTR 中以确保在RAM中运行）
void IRAM_ATTR handleInterrupt() {
  	//Serial.println("InitMax30003Interrupt！");
	//Serial.printf("%.2f\r\n",max30003.ecgdata);
	max30003.getDataIntrupptCallback();
}
void InitMax30003Interrupt()
{
	 /* Set Sampling Rate */
    max30003.max30003SetsamplingRate(SAMPLINGRATE_512);
    /* Set Intruppts */
    max30003.setIntruppts();
	// 设置 GPIO32 为输入，启用内部上拉电阻
	pinMode(inputPin, INPUT_PULLUP);
  
	// 附加中断：下降沿触发，调用 handleInterrupt
	attachInterrupt(digitalPinToInterrupt(inputPin), handleInterrupt, FALLING);
}
//******************************************************* */


void setup()
{
	Serial.begin(115200);

	max30003_Init();
	accel_LIS2DH12_Init();
	BLE_Init();

	InitLed();
	Wire2.begin(FDC2214_SDA, FDC2214_SCL, FDC2214_FREQ);
	// ### Start FDC
  	// Start FDC2212 with 2 channels init
  	bool capOk = capsense.begin(0x3, 0x4, 0x5); //setup first two channels, autoscan with 2 channels, deglitch at 10MHz 
  	// Start FDC2214 with 4 channels init
  	//bool capOk = capsense.begin(0xF, 0x4, 0x5); //setup all four channels, autoscan with 2 channels, deglitch at 10MHz 
  	if (capOk) 
		Serial.println("Sensor OK");  
  	else 
		Serial.println("Sensor Fail");  
#if 0
	Wire1.begin(26, 25);
	if (!tag.begin(Wire1))
  	{
		Serial.println(F("ST25 not detected. Freezing..."));
		while(1)
		{
			//do something
		}
  	}
	//写入EH_MODE，启动后强制打开EH
	uint8_t data[1] = {0x00};
	tag.writeEEPROM(0x0002, data, 1);
	uint8_t data1[1] = {0x01};
	tag.writeEEPROM(0x2002, data1, 1);
#endif

	pinMode(button1.PIN, INPUT_PULLUP);
    attachInterruptArg(button1.PIN, isr, &button1, FALLING);

    Gauss_para_init();

	InitMax30003Interrupt();
}

TimerHandle_t timer_100ms;
#define TIMER_PERIOD_100MS      pdMS_TO_TICKS(100)

static void timer_100ms_handle(TimerHandle_t xTimer)
{
    static uint32_t cnt = 0;
	cnt++;

	if(cnt%10 == 0)//10s采集一次心率和温度
	{
		toggleLed();
		nfc_write_notify = 1;
		cnt = 0;

		//uint8_t data[1];
		//tag.readEEPROM(0x2002, data, 1);
		//Serial.printf("0x2002 = %x \r\n",data[0]);
	}
}

void loop()
{
	timer_100ms = xTimerCreate("TIMER_10HZ", TIMER_PERIOD_100MS, pdTRUE, NULL, timer_100ms_handle);
    xTimerStart(timer_100ms, 0);

	xTaskCreate(
		xTaskOne,  /* Task function. */
		"TaskOne", /* String with name of task. */
		2048,	   /* Stack size in bytes. */
		NULL,	   /* Parameter passed as input of the task */
		12,		   /* Priority of the task.(configMAX_PRIORITIES - 1 being the highest, and 0 being the lowest.) */
		NULL);	   /* Task handle. */

	xTaskCreate(
		xTaskTwo,  /* Task function. */
		"TaskTwo", /* String with name of task. */
		2048,	   /* Stack size in bytes. */
		NULL,	   /* Parameter passed as input of the task */
		12,		   /* Priority of the task.(configMAX_PRIORITIES - 1 being the highest, and 0 being the lowest.) */
		NULL);	   /* Task handle. */

	xTaskCreate(
		xTaskThree,  /* Task function. */
		"TaskThree", /* String with name of task. */
		2048*4,	   /* Stack size in bytes. */
		NULL,	   /* Parameter passed as input of the task */
		12,		   /* Priority of the task.(configMAX_PRIORITIES - 1 being the highest, and 0 being the lowest.) */
		NULL);	   /* Task handle. */
	
	xTaskCreate(
		xTaskForth,  /* Task function. */
		"TaskForth", /* String with name of task. */
		2048,	   /* Stack size in bytes. */
		NULL,	   /* Parameter passed as input of the task */
		12,		   /* Priority of the task.(configMAX_PRIORITIES - 1 being the highest, and 0 being the lowest.) */
		NULL);	   /* Task handle. */

	//最后一个参数至关重要，决定这个任务创建在哪个核上.PRO_CPU 为 0, APP_CPU 为 1,或者 tskNO_AFFINITY 允许任务在两者上运行.
	//xTaskCreatePinnedToCore(xTaskOne, "TaskOne", 4096, NULL, 1, NULL, 0);
	//xTaskCreatePinnedToCore(xTaskTwo, "TaskTwo", 4096, NULL, 2, NULL, 1);

	while (1)
	{
		BLE_Connection_Status();
		//struct tm timeinfo = rtc.getTimeStruct();
  		//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");   //  (tm struct) Sunday, January 17 2021 07:24:38
	}
}
